home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 0.9.1.3 stable / flock-0.9.1.3.en-US.win32.exe / flock / chrome / browser.jar / content / browser / preferences / cookies.js < prev    next >
Text File  |  2006-09-22  |  28KB  |  819 lines

  1. //@line 38 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/components/preferences/cookies.js"
  2.  
  3. const nsICookie = Components.interfaces.nsICookie;
  4.  
  5. var gCookiesWindow = {
  6.   _cm               : Components.classes["@mozilla.org/cookiemanager;1"]
  7.                                 .getService(Components.interfaces.nsICookieManager),
  8.   _ds               : Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
  9.                                 .getService(Components.interfaces.nsIScriptableDateFormat),
  10.   _hosts            : {},
  11.   _hostOrder        : [],
  12.   _tree             : null,
  13.   _bundle           : null,
  14.  
  15.   init: function ()
  16.   {
  17.     var os = Components.classes["@mozilla.org/observer-service;1"]
  18.                        .getService(Components.interfaces.nsIObserverService);
  19.     os.addObserver(this, "cookie-changed", false);
  20.     os.addObserver(this, "perm-changed", false);
  21.     
  22.     this._bundle = document.getElementById("bundlePreferences");
  23.     this._tree = document.getElementById("cookiesList");
  24.     
  25.     this._loadCookies();
  26.     this._tree.treeBoxObject.view = this._view;
  27.     this.sort("rawHost");
  28.     if (this._view.rowCount > 0) 
  29.       this._tree.view.selection.select(0);
  30.       
  31.     document.getElementById("filter").focus();
  32.   },
  33.   
  34.   uninit: function ()
  35.   {
  36.     var os = Components.classes["@mozilla.org/observer-service;1"]
  37.                        .getService(Components.interfaces.nsIObserverService);
  38.     os.removeObserver(this, "cookie-changed");
  39.     os.removeObserver(this, "perm-changed");
  40.   },
  41.   
  42.   _cookieEquals: function (aCookieA, aCookieB, aStrippedHost)
  43.   {
  44.     return aCookieA.rawHost == aStrippedHost &&
  45.            aCookieA.name == aCookieB.name &&
  46.            aCookieA.path == aCookieB.path;
  47.   },
  48.   
  49.   observe: function (aCookie, aTopic, aData) 
  50.   {
  51.     if (aTopic != "cookie-changed")
  52.       return;
  53.     
  54.     if (aCookie instanceof Components.interfaces.nsICookie) {
  55.       var strippedHost = this._makeStrippedHost(aCookie.host);
  56.       if (aData == "changed")
  57.         this._handleCookieChanged(aCookie, strippedHost);
  58.       else if (aData == "added")
  59.         this._handleCookieAdded(aCookie, strippedHost);
  60.     }
  61.     else if (aData == "cleared") {
  62.       this._hosts = {};
  63.       this._hostOrder = [];
  64.     
  65.       var oldRowCount = this._view._rowCount;
  66.       this._view._rowCount = 0;
  67.       this._tree.treeBoxObject.rowCountChanged(0, -oldRowCount);
  68.       this._view.selection.clearSelection();
  69.     }
  70.     
  71.     // We don't yet handle aData == "deleted" - it's a less common case
  72.     // and is rather complicated as selection tracking is difficult
  73.   },
  74.   
  75.   _handleCookieChanged: function (changedCookie, strippedHost) 
  76.   {
  77.     var rowIndex = 0;
  78.     var cookieItem = null;
  79.     if (!this._view._filtered) {
  80.       for (var i = 0; i < this._hostOrder.length; ++i) { // (var host in this._hosts) {
  81.         ++rowIndex;
  82.         var hostItem = this._hosts[this._hostOrder[i]]; // var hostItem = this._hosts[host];
  83.         if (this._hostOrder[i] == strippedHost) { // host == strippedHost) {
  84.           // Host matches, look for the cookie within this Host collection
  85.           // and update its data
  86.           for (var j = 0; j < hostItem.cookies.length; ++j) {
  87.             ++rowIndex;
  88.             var currCookie = hostItem.cookies[j];
  89.             if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
  90.               currCookie.value    = changedCookie.value;
  91.               currCookie.isSecure = changedCookie.isSecure;
  92.               currCookie.isDomain = changedCookie.isDomain;
  93.               currCookie.expires  = changedCookie.expires;
  94.               cookieItem = currCookie;
  95.               break;
  96.             }
  97.           }
  98.         }
  99.         else if (hostItem.open)
  100.           rowIndex += hostItem.cookies.length;
  101.       }
  102.     }
  103.     else {
  104.       // Just walk the filter list to find the item. It doesn't matter that
  105.       // we don't update the main Host collection when we do this, because
  106.       // when the filter is reset the Host collection is rebuilt anyway.
  107.       for (rowIndex = 0; rowIndex < this._view._filterSet.length; ++rowIndex) {
  108.         currCookie = this._view._filterSet[rowIndex];
  109.         if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
  110.           currCookie.value    = changedCookie.value;
  111.           currCookie.isSecure = changedCookie.isSecure;
  112.           currCookie.isDomain = changedCookie.isDomain;
  113.           currCookie.expires  = changedCookie.expires;
  114.           cookieItem = currCookie;
  115.           break;
  116.         }
  117.       }
  118.     }
  119.     
  120.     // Make sure the tree display is up to date...
  121.     this._tree.treeBoxObject.invalidateRow(rowIndex);
  122.     // ... and if the cookie is selected, update the displayed metadata too
  123.     if (cookieItem != null && this._view.selection.currentIndex == rowIndex)
  124.       this._updateCookieData(cookieItem);  
  125.   },
  126.   
  127.   _handleCookieAdded: function (changedCookie, strippedHost)
  128.   {
  129.     var rowCountImpact = 0;
  130.     var addedHost = { value: 0 };
  131.     this._addCookie(strippedHost, changedCookie, addedHost);
  132.     if (!this._view._filtered) {
  133.       // The Host collection for this cookie already exists, and it's not open, 
  134.       // so don't increment the rowCountImpact becaues the user is not going to
  135.       // see the additional rows as they're hidden. 
  136.       if (addedHost.value || this._hosts[strippedHost].open)
  137.         ++rowCountImpact;
  138.     }
  139.     else {
  140.       // We're in search mode, and the cookie being added matches
  141.       // the search condition, so add it to the list. 
  142.       var c = this._makeCookieObject(strippedHost, changedCookie);
  143.       if (this._cookieMatchesFilter(c)) {
  144.         this._view._filterSet.push(this._makeCookieObject(strippedHost, changedCookie));
  145.         ++rowCountImpact;
  146.       }
  147.     }
  148.     // Now update the tree display at the end (we could/should re run the sort
  149.     // if any to get the position correct.)
  150.     var oldRowCount = this._rowCount;
  151.     this._view._rowCount += rowCountImpact;
  152.     this._tree.treeBoxObject.rowCountChanged(oldRowCount - 1, rowCountImpact);
  153.  
  154.     document.getElementById("removeAllCookies").disabled = this._view._filtered;
  155.   },
  156.   
  157.   _view: {
  158.     _filtered   : false,
  159.     _filterSet  : [],
  160.     _filterValue: "",
  161.     _rowCount   : 0,
  162.     _cacheValid : 0,
  163.     _cacheItems : [],
  164.     get rowCount() 
  165.     { 
  166.       return this._rowCount; 
  167.     },
  168.     
  169.     _getItemAtIndex: function (aIndex)
  170.     {
  171.       if (this._filtered)
  172.         return this._filterSet[aIndex];
  173.  
  174.       var start = 0;
  175.       var count = 0, hostIndex = 0;
  176.  
  177.       var cacheIndex = Math.min(this._cacheValid, aIndex);
  178.       if (cacheIndex > 0) {
  179.         var cacheItem = this._cacheItems[cacheIndex];
  180.         start = cacheItem['start'];
  181.         count = hostIndex = cacheItem['count'];
  182.       }
  183.  
  184.       for (var i = start; i < gCookiesWindow._hostOrder.length; ++i) { // var host in gCookiesWindow._hosts) {
  185.         var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host];
  186.         if (!currHost) continue;
  187.         if (count == aIndex)
  188.           return currHost;
  189.         hostIndex = count;
  190.  
  191.         var cacheEntry = { 'start' : i, 'count' : count };
  192.         var cacheStart = count;
  193.  
  194.         if (currHost.open) {
  195.           if (count < aIndex && aIndex <= (count + currHost.cookies.length)) {
  196.             // We are looking for an entry within this host's children, 
  197.             // enumerate them looking for the index. 
  198.             ++count;
  199.             for (var i = 0; i < currHost.cookies.length; ++i) {
  200.               if (count == aIndex) {
  201.                 var cookie = currHost.cookies[i];
  202.                 cookie.parentIndex = hostIndex;
  203.                 return cookie;
  204.               }
  205.               ++count;
  206.             }
  207.           }
  208.           else {
  209.             // A host entry was open, but we weren't looking for an index
  210.             // within that host entry's children, so skip forward over the
  211.             // entry's children. We need to add one to increment for the
  212.             // host value too. 
  213.             count += currHost.cookies.length + 1;
  214.           }
  215.         }
  216.         else
  217.           ++count;
  218.  
  219.         for (var j = cacheStart; j < count; j++)
  220.           this._cacheItems[j] = cacheEntry;
  221.         this._cacheValid = count - 1;
  222.       }
  223.       return null;
  224.     },
  225.  
  226.     _removeItemAtIndex: function (aIndex, aCount)
  227.     {
  228.       var removeCount = aCount === undefined ? 1 : aCount;
  229.       if (this._filtered) {
  230.         this._filterSet.splice(aIndex, removeCount);
  231.         return;
  232.       }
  233.       
  234.       var item = this._getItemAtIndex(aIndex);
  235.       if (!item) return;
  236.       this._invalidateCache(aIndex - 1);
  237.       if (item.container)
  238.         gCookiesWindow._hosts[item.rawHost] = null;
  239.       else {
  240.         var parent = this._getItemAtIndex(item.parentIndex);
  241.         for (var i = 0; i < parent.cookies.length; ++i) {
  242.           var cookie = parent.cookies[i];
  243.           if (item.rawHost == cookie.rawHost &&
  244.               item.name == cookie.name && item.path == cookie.path)
  245.             parent.cookies.splice(i, removeCount);
  246.         }
  247.       }
  248.     },
  249.  
  250.     _invalidateCache: function (aIndex)
  251.     {
  252.       this._cacheValid = Math.min(this._cacheValid, aIndex);
  253.     },
  254.     
  255.     getCellText: function (aIndex, aColumn)
  256.     {
  257.       if (!this._filtered) {
  258.         var item = this._getItemAtIndex(aIndex);
  259.         if (!item) 
  260.           return "";
  261.         if (aColumn.id == "domainCol")
  262.           return item.rawHost;
  263.         else if (aColumn.id == "nameCol")
  264.           return item.name;
  265.       }
  266.       else {
  267.         if (aColumn.id == "domainCol")
  268.           return this._filterSet[aIndex].rawHost;
  269.         else if (aColumn.id == "nameCol")
  270.           return this._filterSet[aIndex].name;
  271.       }
  272.       return "";
  273.     },
  274.  
  275.     _selection: null, 
  276.     get selection () { return this._selection; },
  277.     set selection (val) { this._selection = val; return val; },
  278.     getRowProperties: function (aIndex, aProperties) {},
  279.     getCellProperties: function (aIndex, aColumn, aProperties) {},
  280.     getColumnProperties: function (aColumn, aProperties) {},
  281.     isContainer: function (aIndex)
  282.     {
  283.       if (!this._filtered) {
  284.         var item = this._getItemAtIndex(aIndex);
  285.         if (!item) return false;
  286.         return item.container;
  287.       }
  288.       return false;
  289.     },
  290.     isContainerOpen: function (aIndex) 
  291.     { 
  292.       if (!this._filtered) {
  293.         var item = this._getItemAtIndex(aIndex);
  294.         if (!item) return false;
  295.         return item.open;
  296.       }
  297.       return false;
  298.     },
  299.     isContainerEmpty: function (aIndex) 
  300.     { 
  301.       if (!this._filtered) {
  302.         var item = this._getItemAtIndex(aIndex);
  303.         if (!item) return false;
  304.         return item.cookies.length == 0;
  305.       }
  306.       return false;
  307.     },
  308.     isSeparator: function (aIndex) { return false; },    
  309.     isSorted: function (aIndex) { return false; },    
  310.     canDrop: function (aIndex, aOrientation) { return false; },    
  311.     drop: function (aIndex, aOrientation) {},    
  312.     getParentIndex: function (aIndex) 
  313.     {
  314.       if (!this._filtered) {
  315.         var item = this._getItemAtIndex(aIndex);
  316.         // If an item has no parent index (i.e. it is at the top level) this 
  317.         // function MUST return -1 otherwise we will go into an infinite loop. 
  318.         // Containers are always top level items in the cookies tree, so make 
  319.         // sure to return the appropriate value here.        
  320.         if (!item || item.container) return -1;
  321.         return item.parentIndex;
  322.       }
  323.       return -1;
  324.     },    
  325.     hasNextSibling: function (aParentIndex, aIndex) 
  326.     { 
  327.       if (!this._filtered) {
  328.         // |aParentIndex| appears to be bogus, but we can get the real
  329.         // parent index by getting the entry for |aIndex| and reading the
  330.         // parentIndex field. 
  331.         // The index of the last item in this host collection is the 
  332.         // index of the parent + the size of the host collection, and
  333.         // aIndex has a next sibling if it is less than this value.
  334.         var item = this._getItemAtIndex(aIndex);
  335.         if (item) {
  336.           if (item.container) {
  337.             for (var i = aIndex + 1; i < this.rowCount; ++i) {
  338.               var subsequent = this._getItemAtIndex(i);
  339.               if (subsequent.container) 
  340.                 return true;
  341.             }
  342.             return false;
  343.           }
  344.           else {
  345.             var parent = this._getItemAtIndex(item.parentIndex);
  346.             if (parent && parent.container)
  347.               return aIndex < item.parentIndex + parent.cookies.length;
  348.           }
  349.         }
  350.       }
  351.       return aIndex < this.rowCount - 1;
  352.     },
  353.     hasPreviousSibling: function (aIndex)
  354.     {
  355.       if (!this._filtered) {
  356.         var item = this._getItemAtIndex(aIndex);
  357.         if (!item) return false;
  358.         var parent = this._getItemAtIndex(item.parentIndex);
  359.         if (parent && parent.container)
  360.           return aIndex > item.parentIndex + 1;
  361.       }
  362.       return aIndex > 0;
  363.     },
  364.     getLevel: function (aIndex) 
  365.     {
  366.       if (!this._filtered) {
  367.         var item = this._getItemAtIndex(aIndex);
  368.         if (!item) return 0;
  369.         return item.level;
  370.       }
  371.       return 0;
  372.     },
  373.     getImageSrc: function (aIndex, aColumn) {},    
  374.     getProgressMode: function (aIndex, aColumn) {},    
  375.     getCellValue: function (aIndex, aColumn) {},
  376.     setTree: function (aTree) {},    
  377.     toggleOpenState: function (aIndex) 
  378.     {
  379.       if (!this._filtered) {
  380.         var item = this._getItemAtIndex(aIndex);
  381.         if (!item) return;
  382.         this._invalidateCache(aIndex);
  383.         var multiplier = item.open ? -1 : 1;
  384.         var delta = multiplier * item.cookies.length;
  385.         this._rowCount += delta;
  386.         item.open = !item.open;
  387.         gCookiesWindow._tree.treeBoxObject.rowCountChanged(aIndex + 1, delta);
  388.         gCookiesWindow._tree.treeBoxObject.invalidateRow(aIndex);
  389.       }
  390.     },    
  391.     cycleHeader: function (aColumn) {},    
  392.     selectionChanged: function () {},    
  393.     cycleCell: function (aIndex, aColumn) {},    
  394.     isEditable: function (aIndex, aColumn) 
  395.     { 
  396.       return false; 
  397.     },
  398.     setCellValue: function (aIndex, aColumn, aValue) {},    
  399.     setCellText: function (aIndex, aColumn, aValue) {},    
  400.     performAction: function (aAction) {},  
  401.     performActionOnRow: function (aAction, aIndex) {},    
  402.     performActionOnCell: function (aAction, aindex, aColumn) {}
  403.   },
  404.   
  405.   _makeStrippedHost: function (aHost)
  406.   {
  407.     var formattedHost = aHost.charAt(0) == "." ? aHost.substring(1, aHost.length) : aHost;
  408.     return formattedHost.substring(0, 4) == "www." ? formattedHost.substring(4, formattedHost.length) : formattedHost;
  409.   },
  410.   
  411.   _addCookie: function (aStrippedHost, aCookie, aHostCount)
  412.   {
  413.     if (!(aStrippedHost in this._hosts) || !this._hosts[aStrippedHost]) {
  414.       this._hosts[aStrippedHost] = { cookies   : [], 
  415.                                      rawHost   : aStrippedHost,
  416.                                      level     : 0,
  417.                                      open      : false,
  418.                                      container : true };
  419.       this._hostOrder.push(aStrippedHost);
  420.       ++aHostCount.value;
  421.     }
  422.     
  423.     var c = this._makeCookieObject(aStrippedHost, aCookie);    
  424.     this._hosts[aStrippedHost].cookies.push(c);
  425.   },
  426.   
  427.   _makeCookieObject: function (aStrippedHost, aCookie)
  428.   {
  429.     var host = aCookie.host;
  430.     var formattedHost = host.charAt(0) == "." ? host.substring(1, host.length) : host;
  431.     var c = { name        : aCookie.name,
  432.               value       : aCookie.value,
  433.               isDomain    : aCookie.isDomain,
  434.               host        : aCookie.host,
  435.               rawHost     : aStrippedHost,
  436.               path        : aCookie.path,
  437.               isSecure    : aCookie.isSecure,
  438.               expires     : aCookie.expires,
  439.               level       : 1,
  440.               container   : false };
  441.     return c;
  442.   },
  443.   
  444.   _loadCookies: function () 
  445.   {
  446.     var e = this._cm.enumerator;
  447.     var hostCount = { value: 0 };
  448.     this._hosts = {};
  449.     this._hostOrder = [];
  450.     while (e.hasMoreElements()) {
  451.       var cookie = e.getNext();
  452.       if (cookie && cookie instanceof Components.interfaces.nsICookie) {
  453.         var strippedHost = this._makeStrippedHost(cookie.host);
  454.         this._addCookie(strippedHost, cookie, hostCount);
  455.       }
  456.       else
  457.         break;
  458.     }
  459.     this._view._rowCount = hostCount.value;
  460.   },
  461.   
  462.   formatExpiresString: function (aExpires) 
  463.   {
  464.     if (aExpires) {
  465.       var date = new Date(1000 * aExpires);
  466.       return this._ds.FormatDateTime("", this._ds.dateFormatLong,
  467.                                      this._ds.timeFormatSeconds,
  468.                                      date.getFullYear(),
  469.                                      date.getMonth() + 1,
  470.                                      date.getDate(),
  471.                                      date.getHours(),
  472.                                      date.getMinutes(),
  473.                                      date.getSeconds());
  474.     }
  475.     return this._bundle.getString("AtEndOfSession");
  476.   },
  477.   
  478.   _updateCookieData: function (aItem)
  479.   {
  480.     var seln = this._view.selection;
  481.     var ids = ["name", "value", "host", "path", "isSecure", "expires"];
  482.     var properties;
  483.     
  484.     if (aItem && !aItem.container && seln.count > 0) {
  485.       properties = { name: aItem.name, value: aItem.value, host: aItem.host,
  486.                      path: aItem.path, expires: this.formatExpiresString(aItem.expires),
  487.                      isDomain: aItem.isDomain ? this._bundle.getString("domainColon")
  488.                                               : this._bundle.getString("hostColon"),
  489.                      isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly")
  490.                                               : this._bundle.getString("forAnyConnection") };
  491.       for (var i = 0; i < ids.length; ++i)
  492.         document.getElementById(ids[i]).disabled = false;
  493.     }
  494.     else {
  495.       var noneSelected = this._bundle.getString("noCookieSelected");
  496.       properties = { name: noneSelected, value: noneSelected, host: noneSelected,
  497.                      path: noneSelected, expires: noneSelected, 
  498.                      isSecure: noneSelected };
  499.       for (i = 0; i < ids.length; ++i)
  500.         document.getElementById(ids[i]).disabled = true;
  501.     }
  502.     for (var property in properties)
  503.       document.getElementById(property).value = properties[property];
  504.   },
  505.   
  506.   onCookieSelected: function () 
  507.   {
  508.     var properties, item;
  509.     var seln = this._tree.view.selection;
  510.     if (!this._view._filtered) 
  511.       item = this._view._getItemAtIndex(seln.currentIndex);
  512.     else
  513.       item = this._view._filterSet[seln.currentIndex];
  514.       
  515.     this._updateCookieData(item);
  516.     
  517.     var rangeCount = seln.getRangeCount();
  518.     var selectedCookieCount = 0;
  519.     for (var i = 0; i < rangeCount; ++i) {
  520.       var min = {}; var max = {};
  521.       seln.getRangeAt(i, min, max);
  522.       for (var j = min.value; j <= max.value; ++j) {
  523.         item = this._view._getItemAtIndex(j);
  524.         if (!item) continue;
  525.         if (item.container && !item.open)
  526.           selectedCookieCount += item.cookies.length;
  527.         else if (!item.container)
  528.           ++selectedCookieCount;
  529.       }
  530.     }
  531.     var item = this._view._getItemAtIndex(seln.currentIndex);
  532.     if (item && seln.count == 1 && item.container && item.open)
  533.       selectedCookieCount += 2;
  534.       
  535.     var stringKey = selectedCookieCount == 1 ? "removeCookie" : "removeCookies";
  536.     document.getElementById("removeCookie").label = this._bundle.getString(stringKey);
  537.     
  538.     document.getElementById("removeAllCookies").disabled = this._view._filtered;
  539.     document.getElementById("removeCookie").disabled = !(seln.count > 0);
  540.   },
  541.   
  542.   deleteCookie: function () 
  543.   { 
  544. //@line 628 "/cygdrive/K/tinderbuild/src/flock/mozilla/browser/components/preferences/cookies.js"
  545.     var seln = this._view.selection;
  546.     var tbo = this._tree.treeBoxObject;
  547.     
  548.     if (seln.count < 1) return;
  549.     
  550.     var nextSelected = 0;
  551.     var rowCountImpact = 0;
  552.     var deleteItems = [];
  553.     if (!this._view._filtered) {
  554.       var ci = seln.currentIndex;
  555.       nextSelected = ci;
  556.       var invalidateRow = -1;
  557.       var item = this._view._getItemAtIndex(ci);
  558.       if (item.container) {
  559.         rowCountImpact -= (item.open ? item.cookies.length : 0) + 1;
  560.         deleteItems = deleteItems.concat(item.cookies);
  561.         if (!this._view.hasNextSibling(-1, ci)) 
  562.           --nextSelected;
  563.         this._view._removeItemAtIndex(ci);
  564.       }
  565.       else {
  566.         var parent = this._view._getItemAtIndex(item.parentIndex);
  567.         --rowCountImpact;
  568.         if (parent.cookies.length == 1) {
  569.           --rowCountImpact;
  570.           deleteItems.push(item);
  571.           if (!this._view.hasNextSibling(-1, ci))
  572.             --nextSelected;
  573.           if (!this._view.hasNextSibling(-1, item.parentIndex)) 
  574.             --nextSelected;
  575.           this._view._removeItemAtIndex(item.parentIndex);
  576.           invalidateRow = item.parentIndex;
  577.         }
  578.         else {
  579.           deleteItems.push(item);
  580.           if (!this._view.hasNextSibling(-1, ci)) 
  581.             --nextSelected;
  582.           this._view._removeItemAtIndex(ci);
  583.         }
  584.       }
  585.       this._view._rowCount += rowCountImpact;
  586.       tbo.rowCountChanged(ci, rowCountImpact);
  587.       if (invalidateRow != -1)
  588.         tbo.invalidateRow(invalidateRow);
  589.     }
  590.     else {
  591.       var rangeCount = seln.getRangeCount();
  592.       for (var i = 0; i < rangeCount; ++i) {
  593.         var min = {}; var max = {};
  594.         seln.getRangeAt(i, min, max);
  595.         nextSelected = min.value;        
  596.         for (var j = min.value; j <= max.value; ++j) {
  597.           deleteItems.push(this._view._getItemAtIndex(j));
  598.           if (!this._view.hasNextSibling(-1, max.value))
  599.             --nextSelected;
  600.         }
  601.         var delta = max.value - min.value + 1;
  602.         this._view._removeItemAtIndex(min.value, delta);
  603.         rowCountImpact = -1 * delta;
  604.         this._view._rowCount += rowCountImpact;
  605.         tbo.rowCountChanged(min.value, rowCountImpact);
  606.       }
  607.     }
  608.     
  609.     var psvc = Components.classes["@mozilla.org/preferences-service;1"]
  610.                          .getService(Components.interfaces.nsIPrefBranch);
  611.     var blockFutureCookies = false;
  612.     if (psvc.prefHasUserValue("network.cookie.blockFutureCookies"))
  613.       blockFutureCookies = psvc.getBoolPref("network.cookie.blockFutureCookies");
  614.     for (i = 0; i < deleteItems.length; ++i) {
  615.       var item = deleteItems[i];
  616.       this._cm.remove(item.host, item.name, item.path, blockFutureCookies);
  617.     }
  618.     
  619.     if (nextSelected < 0)
  620.       seln.clearSelection();
  621.     else {
  622.       seln.select(nextSelected);
  623.       this._tree.focus();
  624.     }
  625.   },
  626.   
  627.   deleteAllCookies: function ()
  628.   {
  629.     this._cm.removeAll();
  630.     this._tree.focus();
  631.   },
  632.   
  633.   onCookieKeyPress: function (aEvent)
  634.   {
  635.     if (aEvent.keyCode == 46)
  636.       this.deleteCookie();
  637.   },
  638.   
  639.   _lastSortProperty : "",
  640.   _lastSortAscending: false,
  641.   sort: function (aProperty) 
  642.   {
  643.     var ascending = (aProperty == this._lastSortProperty) ? !this._lastSortAscending : true;
  644.     // Sort the Non-Filtered Host Collections
  645.     if (aProperty == "rawHost") {
  646.       function sortByHost(a, b)
  647.       {
  648.         return a.toLowerCase().localeCompare(b.toLowerCase());
  649.       }
  650.       this._hostOrder.sort(sortByHost);
  651.       if (!ascending)
  652.         this._hostOrder.reverse();
  653.     }
  654.         
  655.     function sortByProperty(a, b) 
  656.     {
  657.       return a[aProperty].toLowerCase().localeCompare(b[aProperty].toLowerCase());
  658.     }
  659.     for (var host in this._hosts) {
  660.       var cookies = this._hosts[host].cookies;
  661.       cookies.sort(sortByProperty);
  662.       if (!ascending)
  663.         cookies.reverse();
  664.     }
  665.     // Sort the Filtered List, if in Filtered mode
  666.     if (this._view._filtered) { 
  667.       this._view._filterSet.sort(sortByProperty);
  668.       if (!ascending)
  669.         this._view._filterSet.reverse();
  670.     }
  671.  
  672.     this._view._invalidateCache(0);
  673.     this._view.selection.clearSelection();
  674.     this._view.selection.select(0);
  675.     this._tree.treeBoxObject.invalidate();
  676.     this._tree.treeBoxObject.ensureRowIsVisible(0);
  677.  
  678.     this._lastSortAscending = ascending;
  679.     this._lastSortProperty = aProperty;
  680.   },
  681.   
  682.   clearFilter: function ()
  683.   {
  684.     // Revert to single-select in the tree
  685.     this._tree.setAttribute("seltype", "single");
  686.     
  687.     // Clear the Filter and the Tree Display
  688.     document.getElementById("filter").value = "";
  689.     this._view._filtered = false;
  690.     this._view._rowCount = 0;
  691.     this._tree.treeBoxObject.rowCountChanged(0, -this._view._filterSet.length);
  692.     this._view._filterSet = [];
  693.  
  694.     // Just reload the list to make sure deletions are respected
  695.     this._loadCookies();
  696.     this._tree.treeBoxObject.view = this._view;
  697.  
  698.     // Restore open state
  699.     for (var i = 0; i < this._openIndices.length; ++i)
  700.       this._view.toggleOpenState(this._openIndices[i]);
  701.     this._openIndices = [];
  702.     
  703.     // Restore selection
  704.     this._view.selection.clearSelection();
  705.     for (i = 0; i < this._lastSelectedRanges.length; ++i) {
  706.       var range = this._lastSelectedRanges[i];
  707.       this._view.selection.rangedSelect(range.min, range.max, true);
  708.     }
  709.     this._lastSelectedRanges = [];
  710.  
  711.     document.getElementById("cookiesIntro").value = this._bundle.getString("cookiesAll");
  712.     document.getElementById("clearFilter").disabled = true;
  713.     document.getElementById("filter").focus();
  714.   },
  715.   
  716.   _cookieMatchesFilter: function (aCookie)
  717.   {
  718.     return aCookie.rawHost.indexOf(this._view._filterValue) != -1 ||
  719.            aCookie.name.indexOf(this._view._filterValue) != -1 || 
  720.            aCookie.value.indexOf(this._view._filterValue) != -1;
  721.   },
  722.   
  723.   _filterCookies: function (aFilterValue)
  724.   {
  725.     this._view._filterValue = aFilterValue;
  726.     var cookies = [];
  727.     for (var i = 0; i < gCookiesWindow._hostOrder.length; ++i) { //var host in gCookiesWindow._hosts) {
  728.       var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host];
  729.       if (!currHost) continue;
  730.       for (var j = 0; j < currHost.cookies.length; ++j) {
  731.         var cookie = currHost.cookies[j];
  732.         if (this._cookieMatchesFilter(cookie))
  733.           cookies.push(cookie);
  734.       }
  735.     }
  736.     return cookies;
  737.   },
  738.   
  739.   _lastSelectedRanges: [],
  740.   _openIndices: [],
  741.   _saveState: function ()
  742.   {
  743.     // Save selection
  744.     var seln = this._view.selection;
  745.     this._lastSelectedRanges = [];
  746.     var rangeCount = seln.getRangeCount();
  747.     for (var i = 0; i < rangeCount; ++i) {
  748.       var min = {}; var max = {};
  749.       seln.getRangeAt(i, min, max);
  750.       this._lastSelectedRanges.push({ min: min.value, max: max.value });
  751.     }
  752.   
  753.     // Save open states
  754.     this._openIndices = [];
  755.     for (i = 0; i < this._view.rowCount; ++i) {
  756.       var item = this._view._getItemAtIndex(i);
  757.       if (item && item.container && item.open)
  758.         this._openIndices.push(i);
  759.     }
  760.   },
  761.   
  762.   _filterTimeout: -1,
  763.   onFilterInput: function ()
  764.   {
  765.     if (this._filterTimeout != -1)
  766.       clearTimeout(this._filterTimeout);
  767.    
  768.     function filterCookies()
  769.     {
  770.       var filter = document.getElementById("filter").value;
  771.       if (filter == "") {
  772.         gCookiesWindow.clearFilter();
  773.         return;
  774.       }        
  775.       var view = gCookiesWindow._view;
  776.       view._filterSet = gCookiesWindow._filterCookies(filter);
  777.       if (!view._filtered) {
  778.         // Save Display Info for the Non-Filtered mode when we first
  779.         // enter Filtered mode. 
  780.         gCookiesWindow._saveState();
  781.         view._filtered = true;
  782.       }
  783.       // Move to multi-select in the tree
  784.       gCookiesWindow._tree.setAttribute("seltype", "multiple");
  785.       
  786.       // Clear the display
  787.       var oldCount = view._rowCount;
  788.       view._rowCount = 0;
  789.       gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, -oldCount);
  790.       // Set up the filtered display
  791.       view._rowCount = view._filterSet.length;
  792.       gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, view.rowCount);
  793.       
  794.       // if the view is not empty then select the first item
  795.       if (view.rowCount > 0)
  796.         view.selection.select(0);
  797.  
  798.       document.getElementById("cookiesIntro").value = gCookiesWindow._bundle.getString("cookiesFiltered");
  799.       document.getElementById("clearFilter").disabled = false;
  800.     }
  801.     window.filterCookies = filterCookies;
  802.     this._filterTimeout = setTimeout("filterCookies();", 500);
  803.   },
  804.   
  805.   onFilterKeyPress: function (aEvent)
  806.   {
  807.     if (aEvent.keyCode == 27) // ESC key
  808.       this.clearFilter();
  809.   },
  810.   
  811.   focusFilterBox: function ()
  812.   { 
  813.     var filter = document.getElementById("filter");
  814.     filter.focus();
  815.     filter.select();
  816.   }
  817. };
  818.  
  819.